﻿#define _CRT_SECURE_NO_WARNINGS
//【进阶】45.智能指针(3)
//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using namespace std;
#include<algorithm>
#include<string>
#include<vector>
#include<list>
//C的主要头文件
//#include<stdio.h>
#include<stdlib.h>
//#include<assert.h>
//#include<string.h> 
#include <thread>
#include <mutex>


//【命名空间】

//【类声明】
class A
{
public:
	~A()
	{
		cout <<"~A()" << endl;
	}
private:
	int _a1;
	int _a2;
};

//对应free()的定制删除器
template<class T>
struct FreeFunc {
	void operator()(T* ptr)
	{
		cout << "free:" << ptr << endl;
		free(ptr);
	}
};
//对应delete[]的定制删除器
template<class T>
struct DeleteArrayFunc {
	void operator()(T* ptr)
	{
		cout << "delete[]" << ptr << endl;
		delete[] ptr;
	}
};

//对应fclose()的定制删除器
struct FileClose{
	void operator()(FILE* ptr)
	{
		cout << "fclose(ptr)" << ptr << endl;
		fclose(ptr);
	}
};

//利用RAII思想设计锁的管理守卫
template<class Mutex>
class LockGuard
{
public:
	LockGuard(Mutex& mtx)
		:_mutex(mtx)
	{
		_mutex.lock();
	}
	~LockGuard()
	{
		//cout << "解锁" << endl;
		_mutex.unlock();
	}
	LockGuard(LockGuard<Mutex>&) = delete;
	LockGuard<Mutex>& operator=(LockGuard<Mutex>&) = delete;
private:
	// 注意这里必须使用引用，否则锁的就不是一个互斥量对象
	Mutex& _mutex;
};

mutex mtx;
static int n = 0;
void Func()
{
	for (size_t i = 0; i < 1000000; ++i)
	{
		LockGuard<mutex> lock(mtx);
		++n;
	}
}


//设计一个只能在堆上创建对象的类
class HeapOnly
{
public:
	static HeapOnly* GetObj()
	{
		return new HeapOnly;
	}
private:
	//禁止公开构造
	HeapOnly() {}

	//禁止拷贝构造
	//HeapOnly(const HeapOnly&);
	// or
	HeapOnly(const HeapOnly&) = delete;
};


//设计一个只能在栈上的类
class StackOnly
{
public:
	static  StackOnly GetObj()
	{
		return  StackOnly();
	}
private:
	StackOnly() {};
	
};

//设计一个单例模式
class Singleton
{
public:
	static Singleton* GetInstance()
	{
		if (_pinst == nullptr)
		{
			_pinst = new Singleton;
		}
		return _pinst;
	}
	Singleton(const Singleton& s) = delete;
private:
	Singleton() {}

	static Singleton* _pinst;
};
Singleton* Singleton::_pinst = nullptr;
//【函数声明】
void Test1();void Test2();void Test3();void Test4();

//【主函数】
int main()
{
	cout << "****主函数开始****" << endl;
	Test1();
	Test2();
	Test3();
	Test4();
	
	cout << "****主函数结束****" << endl;
	return 0;
}

//【函数定义】

/*测试用例*/void Test1()
{
	cout << "****测试用例1开始****"<< endl;
	//定制删除器

	//对应delete
	std::shared_ptr<A> sp1(new A);

	//对应delete[]
	//std::shared_ptr<A> sp2(new A[10]);
	std::shared_ptr<A> sp2(new A[10], DeleteArrayFunc<A>());

	//对应free()
	//std::shared_ptr<A> sp3((A*)malloc(sizeof(A)));
	std::shared_ptr<A> sp3((A*)malloc(sizeof(A)), FreeFunc<A>());

	//对应fclose()
	//std::shared_ptr<A> sp4(fopen("test.txt","w"));
	std::shared_ptr<FILE> sp4(fopen("test.txt","w"), FileClose());

	cout << "****测试用例1结束****" << endl << endl;
}

/*测试用例*/void Test2()
{
	cout << "****测试用例2开始****" << endl;
	int begin = clock();
	thread t1(Func);
	thread t2(Func);
	t1.join();
	t2.join();
	int end = clock();
	cout << n << endl;
	cout << "cost time:" << end - begin << endl;
	cout << "****测试用例2结束****" << endl<<endl;
}

/*测试用例*/void Test3()
{
	cout << "****测试用例3开始****" << endl;
	HeapOnly* p = HeapOnly::GetObj();
	std::shared_ptr<HeapOnly> sp (HeapOnly::GetObj());


	cout << "****测试用例3结束****" << endl << endl;
}

/*测试用例*/void Test4()
{
	cout << "****测试用例4开始****" << endl;
	cout << Singleton::GetInstance() << endl;
	cout << Singleton::GetInstance() << endl;
	cout << "****测试用例4结束****" << endl << endl;
}




//【笔记】
//【进阶】45.智能指针(3)
	//C++中没有GC（垃圾资源回收），new/malloc等资源需要手动释放 
		// new     malloc  fopen   lock
		// delete  free    fclose  unlock
	// RAII（Resource Acquisition Is Initialization）是一种利用对象生命周期来控制程序资源
	// 智能指针是依靠RAII实现的，它是在创建空间时将空间地址再托管给一个智能指针类
	// 解决方法有三
		// 1. 管理权转移 auto_ptr 		
		// 2. 防拷贝     unique_ptr		
		// 3. 引用计数的共享拷贝 shared_ptr,其中循环引用还要用weak_ptr解决
	//C++11中智能指针没有xxx_array\malloc\file的版本，需要使用定制删除器
	// 针对delete[] free() fclose() 
	//RAII本质借助构造和析构实现自动调用和释放
	//内存泄漏相关问题的避免和解决
		// 1. 写C/C++代码时小心谨慎
		// 2. 不好处理的地方多用智能指针
		// 3. 如果已经出现泄漏，可以使用内存泄漏工具检测，时候修改解决
		// 检测工具：linux下的valgrind 
//特殊类的设计
	// 设计模式（Design Pattern）是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
	// 已经学习的设计模式包括迭代器模式（封装性）和适配器模式（复用性）
	// 其他设计模式包括：工厂模式、装饰器模式、观察者模式
	// 重点学习：单例模式：
		// 一个类只能创建一个对象，并提供一个访问它的全局访问点，该实例被所有程序模块共享。
	// 
	// 
	// 



		









